package com.slz3.business.module.afterSaleManagement.aftApplyOrder.steward;

import com.slz3.business.frame.api.alipay.AliPayUtil;
import com.slz3.business.frame.api.wx.WeixinUtil;
import com.slz3.business.frame.enums.AuditFlag;
import com.slz3.business.frame.enums.UsingFlag;
import com.slz3.business.frame.module.Repositorys;
import com.slz3.business.frame.module.Services;
import com.slz3.business.frame.response.RR;
import com.slz3.business.frame.response.ResInfo;
import com.slz3.business.frame.steward.Steward;
import com.slz3.business.frame.util.LocalDT;
import com.slz3.business.frame.util.VE;
import com.slz3.business.module.afterSaleManagement.aftApplyOrder.domain.AftApplyOrder;
import com.slz3.business.module.afterSaleManagement.aftApplyOrder.domain.AftApplyOrderFactory;
import com.slz3.business.module.afterSaleManagement.aftApplyOrder.enums.AfterSaleTypeEnum;
import com.slz3.business.module.afterSaleManagement.aftApplyOrder.enums.AuditStateEnum;
import com.slz3.business.module.afterSaleManagement.aftApplyOrderLine.domain.AftApplyOrderLine;
import com.slz3.business.module.orderManagement.ordOrder.domain.OrdOrder;
import com.slz3.business.module.orderManagement.ordOrderLine.domain.PaymentTypeEnum;
import org.springframework.data.domain.Page;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.*;

public class AftApplyOrderResExecutor {

    protected Mono<ServerResponse> add(ServerRequest req, AftApplyOrder aftApplyOrder) {
        AftApplyOrder aftApplyOrderDBLatest = Services.aftApplyOrder.save(aftApplyOrder);
        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domain(aftApplyOrderDBLatest).build());
    }

    /**
     * known: aftApplyOrderList is not null
     */
    protected Mono<ServerResponse> delete(ServerRequest req) {
        List<AftApplyOrder> aftApplyOrderList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(aftApplyOrderList)) {
            List<AftApplyOrder> aftApplyOrderListNew = Services.aftApplyOrder.delete(aftApplyOrderList);
            if (VE.isNotEmpty(aftApplyOrderListNew) && aftApplyOrderListNew.size() == aftApplyOrderList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(aftApplyOrderListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("delete fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    protected Mono<ServerResponse> modify(ServerRequest req, AftApplyOrder source) {
        AftApplyOrder target = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (target != null) {
            Steward.merge(source, target);
            AftApplyOrder aftApplyOrderDBLatest = Services.aftApplyOrder.modify(target);
            return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domain(aftApplyOrderDBLatest).build());
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    protected Mono<ServerResponse> list(ServerRequest req) {
        Page<AftApplyOrder> aftApplyOrderPage = Services.aftApplyOrder.page(req.queryParams());
        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).theme("page").page(aftApplyOrderPage).build());
    }

    protected Mono<ServerResponse> info(ServerRequest req) {
        AftApplyOrder target = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (target != null) {
            return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domain(target).build());
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    protected Mono<ServerResponse> choice(ServerRequest req) {
        Page<AftApplyOrder> aftApplyOrderPage = Services.aftApplyOrder.page(req.queryParams());
        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).theme("page").page(aftApplyOrderPage).build());
    }

    /**
     * known: aftApplyOrderList is not null
     */
    protected Mono<ServerResponse> auditSubmit(ServerRequest req) {
        List<AftApplyOrder> aftApplyOrderList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(aftApplyOrderList)) {
            aftApplyOrderList.stream().forEach(item -> {
                item.setSerAudit(AuditFlag.WAIT_AUDIT);
                AftApplyOrderFactory.initBaseFields(item);
            });
            List<AftApplyOrder> aftApplyOrderListNew = Services.aftApplyOrderTransactional.batchModify(aftApplyOrderList);
            if (VE.isNotEmpty(aftApplyOrderListNew) && aftApplyOrderListNew.size() == aftApplyOrderList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(aftApplyOrderListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("auditSubmit fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    /**
     * known: aftApplyOrderList is not null
     */
    protected Mono<ServerResponse> audit(ServerRequest req) {
        List<AftApplyOrder> aftApplyOrderList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(aftApplyOrderList)) {

            aftApplyOrderList.stream().forEach(item -> {
                if(item.getSerAfterSaleType().equals(AfterSaleTypeEnum.ONLYMONEY.toString())){
                    item.setSerAuditState(AuditStateEnum.AUDIT_SUCCESS_ALREFUND.getKey());
                }else {
                    item.setSerAuditState(AuditStateEnum.AUDIT_SUCCESS_WAITDELEVER.getKey());
                }
                item.setSerAuditTime(LocalDateTime.now());

                OrdOrder ordOrder = Services.ordOrder.single(item.getSerOrderId()).get();
                if (PaymentTypeEnum.ALYAPY.equals(ordOrder.getSerPaymentType())){
                    Map<String,Object> result =  AliPayUtil.orderPayRefund(ordOrder.getSerOrderNo(),item.getSerMoney().toString(),item.getSerUserReason());
                    if(VE.isEmpty(result)){
                        RR.resDetail(req).put("refund",ordOrder.getSerOrderNo()+"退款失败,交易已关闭或交易不存在!");
                    }else {
                        item.setSerCoding(Optional.ofNullable(result.get("trade_no").toString()).orElse(""));
                    }
                }else if (PaymentTypeEnum.WEIXIN.equals(ordOrder.getSerPaymentType())){
                    Map<String,String> result = WeixinUtil.orderPayRefund(ordOrder.getSerOrderNo(),ordOrder.getSerTotalFee().doubleValue(),item.getSerMoney(),item.getSerUserReason());
                    if(VE.isEmpty(result)){
                        RR.resDetail(req).put("refund",ordOrder.getSerOrderNo()+"退款失败,交易已关闭或交易不存在!");
                    }else {
                        item.setSerCoding(Optional.ofNullable(result.get("refund_id")).orElse(""));
                    }
                }

                item.setSerPayDate(LocalDateTime.now());
                AftApplyOrderFactory.initBaseFields(item);

                List<AftApplyOrderLine> aftApplyOrderLineList = Repositorys.aftApplyOrderLine.findBySerAfterSaleId(item.getUuid());
                aftApplyOrderLineList.forEach(saleLine->saleLine.setSerAuditState(item.getSerAuditState()));
                Services.aftApplyOrderLineTransactional.batchModify(aftApplyOrderLineList);
            });

            if(VE.isNotEmpty(RR.resDetail(req).get("refund"))){
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("refund fail").build());
            }

            List<AftApplyOrder> aftApplyOrderListNew = Services.aftApplyOrderTransactional.batchModify(aftApplyOrderList);
            if (VE.isNotEmpty(aftApplyOrderListNew) && aftApplyOrderListNew.size() == aftApplyOrderList.size()) {
                AftApplyOrderFactory.updateRedisRecord(aftApplyOrderListNew);
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(aftApplyOrderListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("audit fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    /**
     * known: aftApplyOrderList is not null
     */
    protected Mono<ServerResponse> auditReject(ServerRequest req) {
        List<AftApplyOrder> aftApplyOrderList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(aftApplyOrderList)) {
            aftApplyOrderList.stream().forEach(item -> {
                item.setSerAudit(AuditFlag.REJECT);
                AftApplyOrderFactory.initBaseFields(item);
            });
            List<AftApplyOrder> aftApplyOrderListNew = Services.aftApplyOrderTransactional.batchModify(aftApplyOrderList);
            if (VE.isNotEmpty(aftApplyOrderListNew) && aftApplyOrderListNew.size() == aftApplyOrderList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(aftApplyOrderListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("auditReject fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    /**
     * known: aftApplyOrderList is not null
     */
    protected Mono<ServerResponse> usingEnable(ServerRequest req) {
        List<AftApplyOrder> aftApplyOrderList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(aftApplyOrderList)) {
            aftApplyOrderList.stream().forEach(item -> {
                item.setSerUsing(UsingFlag.ENABLE);
                AftApplyOrderFactory.initBaseFields(item);
            });
            List<AftApplyOrder> aftApplyOrderListNew = Services.aftApplyOrderTransactional.batchModify(aftApplyOrderList);
            if (VE.isNotEmpty(aftApplyOrderListNew) && aftApplyOrderListNew.size() == aftApplyOrderList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(aftApplyOrderListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("auditReject fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }


    /**
     * known: aftApplyOrderList is not null
     */
    protected Mono<ServerResponse> usingDisable(ServerRequest req) {
        List<AftApplyOrder> aftApplyOrderList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(aftApplyOrderList)) {
            aftApplyOrderList.stream().forEach(item -> {
                item.setSerUsing(UsingFlag.DISABLE);
                AftApplyOrderFactory.initBaseFields(item);
            });
            List<AftApplyOrder> aftApplyOrderListNew = Services.aftApplyOrderTransactional.batchModify(aftApplyOrderList);
            if (VE.isNotEmpty(aftApplyOrderListNew) && aftApplyOrderListNew.size() == aftApplyOrderList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(aftApplyOrderListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("usingDisable fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    protected Mono<ServerResponse> sync(ServerRequest req, AftApplyOrder aftApplyOrder) {
        Services.aftApplyOrder.sync();
        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).build());
    }

}
